<?php
set_include_path(get_include_path().':./lib/arc2');
//require 'lib/bigfoot/bigfoot.php';
require 'lib/forms/form2rdf.php';
require_once 'lib/converters/converters.php';

class Item
{
	/* The namespaces specified in /config/namespaces.php */
	var $namespaces;
	var $inverted_namespaces;

	/* The store object instantiated from /lib/bigfoot/bigfoot.php */
	var $store;
	var $store_uri;
	var $store_username=false;
	var $store_password=false;
	
	/* request_uri  is the $_SERVER[REQUEST_URI] with the query string stripped off */
	var $request_uri;
	var $location = false;
	/* The $uri of the current resource */
	var $uri;
	var $language ='';
	var $title = '';
	var $parent_template='main';
	var $template;
	var $variables=array();
	
	/* by default, .html */
	var $filename_extension = 'html';
	
	
	/* These can be set in the POST method 
	for displaying form errors and messages */
	var $messages = array();
	var $errors = array();

	/* eg: create, or edit, can be set in /config/routes.php */
	var $action;
	
	var $triples=array();

	/* an Object for converting data */
	var $Convert;
	
	var $headers = array();
	
	var $post_redirect;

	function __construct($params)
	{
		foreach($params as $k => $v)
		{
		 	$this->$k = $v;
		}
		foreach($this->namespaces as $k => $v) $this->inverted_namespaces[$v] = $k;
		
	//	$this->store = new BigfootStore($this->store_uri);
		$this->language = (isset($_GET['language']))? $_GET['language'] : ( isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])?  array_shift(explode(',',$_SERVER['HTTP_ACCEPT_LANGUAGE'])) : 'en-gb');
		$this->Convert = new Converter($this->namespaces, 'lib/arc2/ARC2.php');
		$this->location = 'http://'.($_SERVER['SERVER_NAME'].(($port = $_SERVER['SERVER_PORT'] AND $port!='80')? ':'.$port : '') ).$_SERVER['REQUEST_URI'];

	}

	function Item($params)
	{
		return $this->__construct($params);
	}

	/* responds to HTTP GET method */
	function GET()
	{
		$this->set_variables();

		if(empty($this->variables['resources'][$this->uri]))
		{
			 $this->headers[]="HTTP/1.0 404 Resource not found. ";
			return "HTTP/1.0 404 Resource not found. ";
		}
		elseif(isset($_GET['sparql']))
		{
			$query = urlencode($this->variables['sparql']);
			$this->headers[]="Location: /services/sparql?query={$query}";
			exit;
		}
		return $this->show();
	}
	
		
	/* responds to HTTP POST method */
	function POST()
	{
		$before = $this->store->sparql_service->describe($this->uri);
		$before_rdfxml = $this->Convert->RDFXML->to_resources($before->body)->to_rdfxml();
		foreach($this->Convert->namespaces as $k => $v)$_POST['rdf:RDF']['xmlns:'.$k] =  $v;		
		$posted_rdfxml = Form2RDF::array_to_rdfxml(array('rdf:RDF' => $_POST['rdf:RDF']));

		$cs_args = array(
  			 "subjectOfChange"=> $this->uri,
			 "after_rdfxml"=>  $posted_rdfxml,
			 "createdDate"=>  date("Y-m-d i:s"),
			 "creatorName"=>  $this->template,
			 "changeReason"=>  'Form at '.$this->template.' was posted. ',

			);
			
		if($this->action == 'edit')
		{
			$cs_args['before_rdfxml'] = $before_rdfxml;
		}
		$ChangeSet = new ChangeSet($cs_args);
		$result = $this->store->metabox->apply_changeset($ChangeSet);
		$this->headers[]="HTTP/1.0 ".$result->status_code;
		if($result->status_code=='201')
		{
			if(isset($this->post_redirect)) 
			{
				header("Location: {$this->post_redirect}");
				exit;
			}
			else
			{
				$this->messages[]='Record Saved';
				return $this->GET();
			}
		}
		else
		{
			return $result->status_code; 			
		}

	}
	
	function set_variables()
	{	
		$sparql = <<<_SPARQL_
			prefix rdfs: <{$this->namespaces['rdfs']}>
			prefix rdf: <{$this->namespaces['rdf']}>
			prefix dc: <{$this->namespaces['dc']}>
			prefix foaf: <{$this->namespaces['foaf']}>
			
			construct {
			 <{$this->uri}> ?po ?o .
	  		 ?r ?pr <{$this->uri}> .
			 ?o rdfs:label ?olabel .
			 ?o rdfs:comment ?ocomment .
			 ?o rdfs:seeAlso ?oseealso.
			 ?o rdf:type ?otype .	
			}
			where {
			
			{
				<{$this->uri}> ?po ?o .
				OPTIONAL {
			    ?o rdfs:label ?olabel .
			  }
			  OPTIONAL {
			    ?o rdfs:comment ?ocomment .
			  }
			  OPTIONAL {
			    ?o rdfs:seeAlso ?oseealso.
			  }
			  OPTIONAL {
			    ?o rdf:type ?otype .
			  }
			  OPTIONAL {
			    ?o dc:title ?olabel .
			  }
			  OPTIONAL {
				?o foaf:name ?olabel .
			}
			  OPTIONAL {
				?o ?p ?olabel .
				?p rdfs:subClassOf rdfs:label .
			}
			  
			}


			}
_SPARQL_;

		$this->variables['sparql'] = $sparql;
		$rdfxml = $this->store->sparql_service->GRAPH($sparql);
		$Resources = $this->Convert->RDFXML->to_resources($rdfxml->body);
		$this->namespaces = $Resources->namespaces;
		$this->title = $Resources->to_resource($this->uri)->get_title($this->language);
		$this->variables['resources'] = $Resources->value();
		$this->variables['rdf_xml'] = $rdfxml->body;
	}
	
	
	function show()
	{
			require 'config/mimetypes.php';
			$mtype = $mimetypes[$this->filename_extension];
			$this->headers[]="Content-type: {$mtype}; charset=utf-8";

			foreach($this->headers as $header)
			{
				header($header);
				
				if(substr(trim($header),0,9)=='location:') 	exit;
				if(substr(trim($header),0,12)=='HTTP/1.0 404')
				{
					require_once 'page.php';
					$array['template'] = 'Errors/404';
					$error_page  = new Page($array);
					return $error_page->GET();
				}
			}


	if(is_file($_SERVER['DOCUMENT_ROOT'].'/templates/'.$this->parent_template.'.'.$this->filename_extension))
			{
				return $this->render($this->parent_template);
			}
			elseif(is_file($_SERVER['DOCUMENT_ROOT'].'/templates/'.$this->template.'.'.$this->filename_extension))
			{
				return $this->render($this->template);
			}
			elseif(is_file($_SERVER['DOCUMENT_ROOT'].'/templates/default'.'.'.$this->filename_extension))
			{
				return $this->render('default');
			}
			else
			{
			 	$this->headers[]="HTTP/1.0 404 Resource not found";
				return 'Template not found';
			}
	}
	
	
	/* renders template */
	function render($template)
	{
		require_once('templates/helpers.php');
		if(!defined('LANGUAGE')) define('LANGUAGE', $this->language);
		
		if(!empty($this->namespaces))
		{
			foreach($this->namespaces as $prefix => $uri)
			{
				$constant = strtoupper($prefix);
				
				if(!defined($constant)) define(strtoupper($prefix), $uri);
			}
		}
		
		if(!function_exists('url_id')) eval('function url_id($in){ return str_replace("=","",base64_encode($in));}');
		
		if(	isset($this->variables['resources']) && 
			isset($this->uri) &&
			isset($this->variables['resources'][$this->uri]) &&
			isset($this->variables['resources'][$this->uri]['dir:etag'])
			) $this->headers[]="Etag: {$this->variables['resources'][$this->uri]['dir:etag'][0]['value']}";

		extract($this->variables);
		ob_start();
		require $_SERVER['DOCUMENT_ROOT'].'/templates/'.$template.'.'.$this->filename_extension;
		return ob_get_clean();
	}
	
	
	/*
	rdf_to_assoc_array($rdfxml)
	
	 transforms RDF/XML to a php associative array version 
	of the RDF/JSON format specified at http://lpag-wiki.talis.com/wiki/rdf-json_Brainstorming
	with the exception that the associative array of resources occurs under a "resources" key instead of at the same level as "prefixes"
	*/
	
	function rdf_to_assoc_array($rdfxml)
	{
		$ns = 1;
		$parser = new ARC_rdfxml_parser(array('base'=>'','bnode_prefix'=>''));
		$parser->parse_data($rdfxml);
		$triples = $parser->get_triples();

		$this->triples = array_merge($this->triples, $triples);
		
		// this is the rdf/php data object
		$rdf_php = array();		
		foreach($triples as $t)
		{
			$o = array();
			if(isset($t['o']['uri']))
			{
				$o['type'] = 'uri';
				$o['value'] = $t['o']['uri'];
			}
			elseif(isset($t['o']['val']))
			{
				$o['type'] = 'literal';
				$o['value'] = $t['o']['val'];
			}
			elseif(isset($t['o']['bnode_id']))
			{
				$o['type'] = 'bnode';
				$o['value'] = $t['o']['bnode_id'];
			}

			$p = $this->uri_to_qname($t['p']);
			
			$o['lang'] = (isset($t['o']['lang']))? $t['o']['lang'] : null;
			$o['datatype'] = (isset($t['o']['dt']))? $t['o']['dt'] : null;
			$bnode_or_uri = (isset($t['s']['uri']))? 'uri': 'bnode_id';
			$rdf_php[$t['s'][$bnode_or_uri]][$p][]=$o;
		}

		return $rdf_php;
	}
	
	function uri_to_qname($p)
	{
		$ns=count($this->namespaces);$ns++;
		$p_parts =  $this->split_uri($p, true);
		
		$prefix = (isset($this->inverted_namespaces[$p_parts[0]]))? $this->inverted_namespaces[$p_parts[0]] : 'ns'.$ns;
		
		if(!isset($this->inverted_namespaces[$p_parts[0]]))
		{
			$this->namespaces[$prefix] = $p_parts[0];
			$this->inverted_namespaces[$p_parts[0]] = $prefix;
		}
		
		return $prefix.':'.$p_parts[1];
	}
	
	function get_labels($resources)
	{
		if(empty($resources)) return array();
		$terms = array();
		foreach($resources as $uri => $properties)
		{
			foreach($properties as $p => $objs)
			{
				$terms[]=($p);
			}
		}
		$terms = array_unique($terms);
		$clauses = array();
		$i=1;
		// foreach($terms as $term) $clauses[]='<'.$term.'> rdfs:label ?label'.$i++;
		// $query =  'PREFIX rdfs: <'.$this->namespaces['rdfs'].'> CONSTRUCT { '.implode(' . ', $clauses).' } WHERE { OPTIONAL {'.implode(' . } OPTIONAL { ', $clauses).'  } } ';
		// $response = $this->store->sparql_service->graph($query);
		// if($response->status_code==200)
		// {
		// 	$parser = new ARC_rdfxml_parser(array('base'=>'','bnode_prefix'=>''));
		// 	$parser->parse_data($response->body);
		// 	$triples = $parser->get_triples();
		// 	$labels = array();
		// 	foreach($triples as $t)
		// 	{
		// 		 if(!isset($labels[$t['s']['uri']]))
		// 		 { 
		// 			if(isset($t['o']['value'])) $labels[$t['s']['uri']] = $this->Convert->URI->to_label($t['o']['value']);
		// 		 }
		// 	}
		// }
		foreach($terms as $term)
		{
			 if ( empty($labels[$term]) ) 
			{
				$labels[$term] = $this->Convert->URI->to_label($term);
			}
		}
		$this->variables['labels'] = $labels;
		return $labels;
	}
	
	function qname_to_uri($qname)
	{
		$parts = explode(':',$qname);
		$prefix = $parts[0];
		$base = $this->namespaces[$prefix];
		return $base.$parts[1];
	}
	
	
	function split_uri($term_uri, $all_matches = false)
	{
		preg_match('@(.+?[/#])([^/#]+)$@',$term_uri, $p_match);
		array_shift($p_match);
		return ($all_matches)? $p_match : $p_match[1];
		 
	}
	
	function get_title()
	{
		return $this->title;
	}
}


?>